package reesoft.common.util;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

/**
 * 公用的应用程序上下文单元，可获取应用程序上下文和 Bean
 *
 * Created by reesoft on 2017-07-14
 */
@Component
@Lazy(false)
public class ApplicationContextUtil implements ApplicationContextAware, DisposableBean
{
    private static ApplicationContext applicationContext = null;

    /**
     * 取得应用程序上下文
     */
    public static ApplicationContext getApplicationContext()
    {
        assertContextInjected();
        return applicationContext;
    }

    /**
     * 从应用程序上下文取得 Bean
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(final String name)
    {
        assertContextInjected();
        return (T) applicationContext.getBean(name);
    }

    /**
     * 从应用程序上下文取得 Bean
     */
    public static <T> T getBean(final Class<T> requiredType)
    {
        assertContextInjected();
        return applicationContext.getBean(requiredType);
    }

    /**
     * 实现 ApplicationContextAware 接口, 存储应用程序上下文
     */
    @Override
    public void setApplicationContext(final ApplicationContext applicationContext)
    {
        ApplicationContextUtil.applicationContext = applicationContext;
    }

    /**
     * 实现 DisposableBean 接口, 清除存储的应用程序上下文
     */
    @Override
    public void destroy() throws Exception
    {
        applicationContext = null;
    }

    /**
     * 断言应用程序上下文已存储
     */
    private static void assertContextInjected()
    {
        if (applicationContext == null)
        {
            throw new IllegalStateException(
                    "ApplicationContext is not set, a bean of class ApplicationContextUtil should be defined.");
        }
    }
}
